#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
#endregion

namespace KLib.PostProcessing
{
    /// <summary>
    /// Manages all Post Processing effects. Simply add a PostProcessingEffect to the manager,
    /// and it will take care of the rest
    /// </summary>
    public class PostProcessingManager : Microsoft.Xna.Framework.DrawableGameComponent
    {
        #region Fields
        private RenderTarget2D renderTarget;
        private ResolveTexture2D backBuffer;
        private SpriteBatch spriteBatch;

        private Dictionary<string,PostProcessingEffect> effects;
        #endregion

        #region Properties
        public Dictionary<string,PostProcessingEffect> Effects
        {
            get { return effects; }
        }
        #endregion

        #region Initializiation
        public PostProcessingManager(Game game)
            : base(game)
        {
        }

        public override void Initialize()
        {
            // TODO: Add your initialization code here
            this.DrawOrder = int.MaxValue-10;
            effects = new Dictionary<string,PostProcessingEffect>();
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            backBuffer = new ResolveTexture2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 1, SurfaceFormat.Color);
            base.LoadContent();
        }
        #endregion

        #region Methods
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here
            foreach (PostProcessingEffect effect in effects.Values)
            {
                if (effect.Enabled)
                    effect.Update(gameTime);
            }
            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            foreach (PostProcessingEffect effect in effects.Values)
            {
                if (effect.Enabled)
                {
                    GraphicsDevice.ResolveBackBuffer(backBuffer);
                    GraphicsDevice.Clear(Color.Black);

                    spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None);

                    GraphicsDevice.Textures[0] = backBuffer;

                    effect.Begin();
                    spriteBatch.Draw(backBuffer, Vector2.Zero, Color.White);

                    spriteBatch.End();
                    effect.End();
                }
            }
            base.Draw(gameTime);
        }

        public void Add(string name, PostProcessingEffect effect)
        {
            if (effects.ContainsKey(name))
                return;

            effect.Manager = this;
            effect.LoadContent();
            this.effects.Add(name, effect);
        }

        public void Remove(string name)
        {
            this.effects.Remove(name);
        }

        public void SetParamater(string effectName, string parameterName, object value)
        {
            this.Effects[effectName].SetParameter(parameterName, value);
        }
        #endregion
    }
}